// 剖切面数组
let clippingHandlers

/**
 * 名称：创建体剖切
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：
 * 状态：
 * 网址：
 * 负责人：
 */
function createSection(options) {
  // 合并配置项
  clipdata = {
    ...clipdata,
    // planeColor: Cesium.Color.RED.withAlpha(0.8),
    arrowColor: Cesium.Color.BLUE.withAlpha(0.8), // 箭头颜色
    arrowSize: [20, 15], // 箭头大小,接收一个数组，用于指定箭头的宽和长
    boxSize: 20 || [10, 20, 30], // 体剖切盒子大小 默认正方形 边长为5，也可接收一个数组 [10,20,30]，用于指定长宽高
    position: null, // 体剖盒子中心点坐标
    displayBoxInterior: true,// 是否显示盒子内部
    ...options
  }
  clipdata.displayBoxInterior = clipdata.displayBoxInterior ? 1 : -1
  console.log('clipdata.displayBoxInterior', clipdata.displayBoxInterior)
  if(clipdata.position) {
    // 存在
    clipdata.center = clipdata.position
    callClippingEvent()
  } else {
    clippingHandlers = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
    clippingHandlers.setInputAction((e) => {
      const pickedObject = viewer.scene.pick(e.position)
      console.log('pickedObject', pickedObject)
      if(Cesium.defined(pickedObject)) {
        clipdata.center = viewer.scene.pickPosition(e.position)
        callClippingEvent()
        // 移除该点击事件
        clippingHandlers.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
      }

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  }
}

/**
 * 剖切方法调用
 */
const callClippingEvent = () => {
  ClippingBox.prototype.open()
  ClippingBox()
  // for(let i = 0; i < globalTilesetArr.length; i++) {
  //   console.log('globalTilesetArr[i]', globalTilesetArr[i])
  //   // globalTilesetArr[i].clippingPlanes = createClippingPlanes()
  //   ClippingBox.prototype.setTarget(globalTranslationArr[i])
  //
  // }
  ClippingBox.prototype.setTarget(globalTranslationArr[0])

}

/**
 * 名称：销毁剖切剖切
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：
 * 状态：
 * 网址：
 * 负责人：
 */
function deleteSection() {
  ClippingBox.prototype.close()
}

/**
 * 名称：剖面框
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：
 * 状态：
 * 网址：
 * 负责人：
 */
function ClippingBox() {
  // 鼠标移动事件
  clippingHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  clippingHandler.setInputAction((e) => {
    // console.log('鼠标移动了')
    if(flags.opened === true) {
      const pickedObject = viewer.scene.pick(e.endPosition)
      // console.log('pickedObject', pickedObject)
      if(Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
        // pickedObject.id.polyline._material._color._value = Cesium.Color.YELLOW.withAlpha(0.8)
      }
      if(Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && Cesium.defined(pickedObject.id.box)) {
        if(clippingEntityArray.length > 0) {
          clippingEntityArray[0].box.outlineColor = colors[1]
        }
      } else {
        if(clippingEntityArray.length > 0) {
          clippingEntityArray[0].box.outlineColor = flags.selected ? colors[2] : colors[0]
        }
      }
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

  // 鼠标点击事件
  clippingHandler.setInputAction((e) => {

    // const pickedObject = viewer.scene.pick(e.position)
    // if(flags.opened === true && Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && Cesium.defined(pickedObject.id.box)) {
    if(flags.opened === true) {
      // 删除锚点
      for(let i = 0; i < anchorEntityArray.length; i++) {
        viewer.entities.remove(anchorEntityArray[i])
      }
      anchorEntityArray = []

      const pickedObject = viewer.scene.pick(e.position)
      if(Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && Cesium.defined(pickedObject.id.box)) {
        if(clippingEntityArray.length > 0) {
          clippingEntityArray[0].box.outlineColor = colors[2]
          flags.selected = true
        }

        // 重新计算锚点
        for(let i = 0; i < clipdata.centers.length; i++) {
          const anchorEntity = addPoint(viewer, clipdata.centers[i], directions[i], i, clipdata.normals[i])
          anchorEntityArray.push(anchorEntity)
        }
      } else if(flags.selected) {
        flags.selected = false
        if(clippingEntityArray.length > 0) {
          clippingEntityArray[0].box.outlineColor = colors[0]
        }
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

  // 是否是锚点
  function isAnchor(pickedObject) {
    return pickedObject && pickedObject.id && pickedObject.id.direction && directions.indexOf(pickedObject.id.direction) !== -1
  }

  /**
   * 同步当前锚点（处理前后左右）
   * @param dragedAnchor 当前抓住的锚点对象
   * @param index 当前锚点对象的下标
   * @param pickPosition 鼠标移动的end点的对应的地形坐标
   * @return {Cesium.Cartesian3}
   */
  function updateFBLRAnchor(dragedAnchor, index, pickPosition) {
    // 计算投影向量
    const translation = new Cesium.Cartesian3()
    if(prevPickPosition) {
      //  a(x1,y1,z1) b(x,y,z)
      // subtract 这个方法求的是两点构成的向量，即一个向量的坐标等于其终点坐标减去始点坐标
      // subtract（a,b） = a - b = (x1-x,y1-y,z1-z)
      Cesium.Cartesian3.subtract(pickPosition, prevPickPosition, translation)
      Cesium.Cartesian3.projectVector(translation, clipdata.normals[index], translation)

      // 计算新的中心点并同步锚点
      const position = new Cesium.Cartesian3()
      Cesium.Cartesian3.add(clipdata.centers[index], translation, position)
      clipdata.centers[index] = position.clone()
      dragedAnchor.id.position = position.clone()
    }
    prevPickPosition = pickPosition
    return translation
  }

  // 同步当前锚点(处理上下)
  function updateTBAnchor(dragedAnchor, index, startPosition, endPosition) {
    console.log('index', index)
    // 计算投影向量
    const v = Cesium.Cartesian2.subtract(startPosition, endPosition, new Cesium.Cartesian2())
    const delta = Math.abs(v.x) > Math.abs(v.y) ? v.x : v.y

    const translation = new Cesium.Cartesian3()
    Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_Z, delta, translation)
    Cesium.Cartesian3.projectVector(translation, clipdata.normals[index], translation)

    // 计算新的中心点并同步锚点
    const position = new Cesium.Cartesian3()
    Cesium.Cartesian3.add(clipdata.centers[index], translation, position)
    clipdata.centers[index] = position.clone()
    dragedAnchor.id.position = position.clone()

    return translation
  }

  // 同步相邻锚点
  function updateAdjoinAnchorEntity(index, originCenter, translation) {
    const position = new Cesium.Cartesian3()
    Cesium.Cartesian3.add(originCenter, translation, position)
    clipdata.centers[index] = position.clone()
    // console.log('anchorEntityArray[index]', anchorEntityArray[index])
    // anchorEntityArray[index]._polyline.positions = [position.clone(), Cesium.Cartesian3.lerp(clipdata.center, position, 1.2, new Cesium.Cartesian3())]
    // 更新中心点
    updateOringin()
  }

  // 同步虚拟剖面框
  function updateClippingEntityPosition(clippingEntity, center, oppCenter) {
    const position = new Cesium.Cartesian3()
    Cesium.Cartesian3.midpoint(center, oppCenter, position)
    clippingEntity.position = position
  }

  // 更新真实剖面框
  function updateClippingPlanes(index, translation) {
    if(index < 0 || index > 5) return
    if(clippingTargetArray.length > 0) {
      const clippingPlanes = clippingTargetArray[0].clippingPlanes
      const plane = clippingPlanes.get(index)
      if(plane.direction === 'front' || plane.direction === 'behind') {
        const distance = clipdata.displayBoxInterior * Cesium.Cartesian3.distance(clipdata.centers[0], clipdata.centers[1])
        const plane1 = clippingPlanes.get(0)
        plane1.distance = distance / 2
        const plane2 = clippingPlanes.get(1)
        plane2.distance = distance / 2
      } else if(plane.direction === 'left' || plane.direction === 'right') {
        const distance = clipdata.displayBoxInterior * Cesium.Cartesian3.distance(clipdata.centers[2], clipdata.centers[3])
        const plane1 = clippingPlanes.get(2)
        plane1.distance = distance / 2
        const plane2 = clippingPlanes.get(3)
        plane2.distance = distance / 2
      } else if(plane.direction === 'top' || plane.direction === 'bottom') {
        const distance = clipdata.displayBoxInterior * Cesium.Cartesian3.distance(clipdata.centers[4], clipdata.centers[5])
        const plane1 = clippingPlanes.get(4)
        plane1.distance = distance / 2
        const plane2 = clippingPlanes.get(5)
        plane2.distance = distance / 2
      }
      // 同步真实剖面框
      const m3 = new Cesium.Matrix3()
      Cesium.Matrix4.getMatrix3(clippingTargetArray[0].root.transform, m3)
      Cesium.Matrix3.inverse(m3, m3)
      const vector = Cesium.Matrix3.multiplyByVector(m3, translation, new Cesium.Cartesian3())
      const m4 = new Cesium.Matrix4()
      Cesium.Matrix4.fromTranslation(vector, m4)
      Cesium.Matrix4.multiply(clippingPlanes.modelMatrix, m4, m4)
      clippingPlanes.modelMatrix = m4
    }
  }

  // 拖拽锚点，缩放剖面框，鼠标按下
  viewer.screenSpaceEventHandler.setInputAction((e) => {
    const pickedObject = viewer.scene.pick(e.position)
    // 是否点击的是锚点
    if(isAnchor(pickedObject)) {
      // 是
      leftDownFlag = true // 左键已按下
      dragedAnchor = pickedObject //将选中实体赋给拖拽锚点变量
      dragedAnchor.id.polyline._material._color._value = Cesium.Color.YELLOW.withAlpha(0.8)
      // 禁用Cesium.js中的屏幕空间相机控制器的输入功能
      viewer.scene.screenSpaceCameraController.enableInputs = false
    }
    // else if(pickedObject.id.id === 'ClippingEntity1') {
    //   console.log('pickedObject.id.id', pickedObject.id.id)
    //   //  点击的是
    //   leftDownFlag = true // 左键已按下
    //   dragedCenter = pickedObject //将选中实体赋给拖拽锚点变量
    //   // 禁用Cesium.js中的屏幕空间相机控制器的输入功能
    //   viewer.scene.screenSpaceCameraController.enableInputs = false
    // }
  }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
  // 鼠标抬起
  viewer.screenSpaceEventHandler.setInputAction((e) => {
    // 开启Cesium.js中的屏幕空间相机控制器的输入功能
    viewer.scene.screenSpaceCameraController.enableInputs = true
    // 左键已抬起
    leftDownFlag = false
    dragedAnchor && (dragedAnchor.id.polyline._material._color._value = Cesium.Color.BLUE.withAlpha(0.8))
    dragedAnchor && (dragedAnchor = null) //清空拖拽锚点变量
    dragedCenter && (dragedCenter = null)//清空拖拽中心点变量
    prevPickPosition = null //前一个拾取坐标（或对象）
  }, Cesium.ScreenSpaceEventType.LEFT_UP)

  // 鼠标移动事件
  viewer.screenSpaceEventHandler.setInputAction((e) => {
    if(leftDownFlag === true && dragedAnchor != null) {
      // 左键按下且未松开，选中锚点实体存在
      const ray = viewer.camera.getPickRay(e.endPosition) //根据屏幕坐标生成一条射线
      const pickPosition = viewer.scene.globe.pick(ray, viewer.scene) // 该射线与三维场景的交点
      // viewer.scene.pick(e.position) 拾取实体
      // viewer.scene.pickPosition(e.position)  场景坐标
      // viewer.scene.globe.pick(viewer.camera.getPickRay(e.position), viewer.scene))  地表坐标
      // viewer.camera.pickEllipsoid(e.position)  世界坐标

      if(pickPosition && clipdata.centers.length === 6 && clipdata.normals.length === 6 && clippingEntityArray.length > 0) {
        // 计算锚点索引
        const index = directions.indexOf(dragedAnchor.id.direction)
        if(dragedAnchor.id.direction === 'front' || dragedAnchor.id.direction === 'behind') {
          const translation = updateFBLRAnchor(dragedAnchor, index, pickPosition)
          // 同步和中心相邻的点：前后左右上下中的左右上下，同时同步锚点
          Cesium.Cartesian3.divideByScalar(translation, 2, translation) //将提供的笛卡尔分量除以提供的标量。
          updateAdjoinAnchorEntity(2, clipdata.centers[2], translation)
          updateAdjoinAnchorEntity(3, clipdata.centers[3], translation)
          updateAdjoinAnchorEntity(4, clipdata.centers[4], translation)
          updateAdjoinAnchorEntity(5, clipdata.centers[5], translation)
          // 同步虚拟剖面框
          updateClippingEntityPosition(clippingEntityArray[0], clipdata.centers[0], clipdata.centers[1])
          // 同步真实剖面框
          updateClippingPlanes(index, translation)
        } else if(dragedAnchor.id.direction === 'left' || dragedAnchor.id.direction === 'right') {
          const translation = updateFBLRAnchor(dragedAnchor, index, pickPosition)
          // 同步和中心相邻的点：前后左右上下中的前后上下，同时同步锚点
          Cesium.Cartesian3.divideByScalar(translation, 2, translation)
          updateAdjoinAnchorEntity(0, clipdata.centers[0], translation)
          updateAdjoinAnchorEntity(1, clipdata.centers[1], translation)
          updateAdjoinAnchorEntity(4, clipdata.centers[4], translation)
          updateAdjoinAnchorEntity(5, clipdata.centers[5], translation)
          // 同步虚拟剖面框
          updateClippingEntityPosition(clippingEntityArray[0], clipdata.centers[2], clipdata.centers[3])
          // 同步真实剖面框
          updateClippingPlanes(index, translation)
        } else if(dragedAnchor.id.direction === 'top' || dragedAnchor.id.direction === 'bottom') {
          const translation = updateTBAnchor(dragedAnchor, index, e.startPosition, e.endPosition)
          // 同步和中心相邻的点：前后左右上下中的前后左右，同时同步锚点
          Cesium.Cartesian3.divideByScalar(translation, 2, translation)
          updateAdjoinAnchorEntity(0, clipdata.centers[0], translation)
          updateAdjoinAnchorEntity(1, clipdata.centers[1], translation)
          updateAdjoinAnchorEntity(2, clipdata.centers[2], translation)
          updateAdjoinAnchorEntity(3, clipdata.centers[3], translation)
          // 同步虚拟剖面框
          updateClippingEntityPosition(clippingEntityArray[0], clipdata.centers[4], clipdata.centers[5])
          // 同步真实剖面框
          updateClippingPlanes(index, translation)
        }
      }
    } else if(leftDownFlag === true && dragedCenter != null) {
      // const ray = viewer.camera.getPickRay(e.endPosition) //根据屏幕坐标生成一条射线
      // const pickPosition = viewer.scene.globe.pick(ray, viewer.scene) // 该射线与三维场景的交点
      clipdata.center = viewer.scene.pickPosition(e.endPosition)
      // if(pickPosition && clipdata.centers.length === 6 && clipdata.normals.length === 6 && clippingEntityArray.length > 0) {
      //   // 计算锚点索引
      //   const translation = updateTBAnchor(clippingEntityArray[0], 0, e.startPosition, e.endPosition)
      //   // 同步和中心相邻的点：前后左右上下中的前后左右，同时同步锚点
      //   Cesium.Cartesian3.divideByScalar(translation, 2, translation)
      //   updateAdjoinAnchorEntity(1, clipdata.centers[1], translation)
      //   updateAdjoinAnchorEntity(2, clipdata.centers[2], translation)
      //   updateAdjoinAnchorEntity(3, clipdata.centers[3], translation)
      //   updateAdjoinAnchorEntity(4, clipdata.centers[4], translation)
      //   updateAdjoinAnchorEntity(5, clipdata.centers[5], translation)
      //   // 同步虚拟剖面框
      //   updateClippingEntityPosition(clippingEntityArray[0], clipdata.centers[4], clipdata.centers[5])
      //   // 同步真实剖面框
      //   updateClippingPlanes(index, translation)
      // }

      // 拽住中心点进行移动
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}

/**
 * 名称：剖切是否开启
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：
 * 状态：
 * 网址：
 * 负责人：
 */
ClippingBox.prototype.isOpened = function() {
  return flags.opened
}

/**
 * 名称：开启剖切
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：
 * 状态：
 * 网址：
 * 负责人：
 */
ClippingBox.prototype.open = function() {
  if(flags.opened === false) {
    flags.opened = true
  }
}

/**
 * 名称：关闭剖切
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：
 * 状态：
 * 网址：
 * 负责人：
 */
ClippingBox.prototype.close = function() {
  if(flags.opened === true) {
    flags.opened = false
    flags.selected = false
  }

  // 删除锚点
  for(let i = 0; i < anchorEntityArray.length; i++) {
    viewer.entities.remove(anchorEntityArray[i])
  }
  anchorEntityArray = []

  // 删除剖面框
  for(let i = 0; i < clippingEntityArray.length; i++) {
    viewer.entities.remove(clippingEntityArray[i])
    globalTilesetArr[i]?.clippingPlanes && (globalTilesetArr[i].clippingPlanes._planes = [])

  }
  clippingEntityArray = []

  // 清除目标对象
  if(clippingTargetArray.length > 0) {
    // clippingTargetArray[0].clippingPlanes.enabled = false
    clippingTargetArray = []
  }

  // globalTilesetArr[0].clippingPlanes._planes = []
  // 清除data
  clipdata.centers = []
  clipdata.normals = []

  //  移除事件
  clippingHandlers && clippingHandlers.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
  clippingHandler && clippingHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
  clippingHandler && clippingHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
  viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN)
  viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP)
  viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}

/**
 * 名称：设置剖切对象
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
ClippingBox.prototype.setTarget = function(target) {
  if(!flags.opened) return
  // if(clippingTargetArray.length > 0 && clippingTargetArray[0] === target) return

  if(target instanceof Cesium.Cesium3DTileset) {

    ClippingBox.prototype.set3DTileset(target)
  }
}

/**
 * 名称：设置剖切对象
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
ClippingBox.prototype.set3DTileset = function(tileset) {
  clippingTargetArray.push(tileset)
  tileset.readyPromise.then(() => {
    let a = createClippingPlanes()
    for(let i = 0; i < globalTilesetArr.length; i++) {
      console.log('globalTilesetArr[i]', globalTilesetArr[i])
      globalTilesetArr[i].clippingPlanes = a
      // globalTilesetArr[i].clippingPlanes = createClippingPlanes()

    }
    // tileset.clippingPlanes = createClippingPlanes()
    // const boundingSphere = tileset.boundingSphere
    // const center = boundingSphere.center
    // const radius = boundingSphere.radius
    // 计算剖面框中心位置
    // clipdata.center = center.clone()
    //由经度、纬度和高度定义的位置。
    const cartCenter = Cesium.Cartographic.fromCartesian(clipdata.center)
    // 计算剖面框旋转
    const m3 = Cesium.Matrix4.getMatrix3(tileset.root.transform, new Cesium.Matrix3())
    // 从提供的 Matrix3（3x3旋转矩阵） 实例计算四元数。
    const quaternion = Cesium.Quaternion.fromRotationMatrix(m3, new Cesium.Quaternion()) //四元数
    const clippingPlanes = tileset.clippingPlanes
    for(let i = 0; i < clippingPlanes.length; ++i) {
      const plane = clippingPlanes.get(i)
      if(clipdata.boxSize instanceof Array) {
        if(clipdata.boxSize.length < 3) {
          throw new Error('[err]:boxSize参数错误')
        }
        //  数组
        if(plane.direction === 'front' || plane.direction === 'behind') {
          plane.distance = clipdata.boxSize[1] // 高

        } else if(plane.direction === 'bottom' || plane.direction === 'top') {
          plane.distance = clipdata.boxSize[2] // 宽

        } else if(plane.direction === 'left' || plane.direction === 'right') {
          plane.distance = clipdata.boxSize[0] // 长
        }
      } else {
        plane.distance = clipdata.boxSize

      }
      plane.distance *= clipdata.displayBoxInterior
      if(plane.direction === 'front' || plane.direction === 'behind' || plane.direction === 'left' || plane.direction === 'right') {
        // 先将平面向量于模型矩阵对齐
        // 航向，俯仰，滚动角
        const hpr = ClippingBox.quaternionToHeadingPitchRoll(clipdata.center, quaternion)
        // 根据航向，俯仰，滚动角 计算旋转三阶矩阵m
        const m = Cesium.Matrix3.fromHeadingPitchRoll(hpr, new Cesium.Matrix3())
        // 计算矩阵和列向量的乘积。,
        const normal = Cesium.Matrix3.multiplyByVector(m, plane.normal, new Cesium.Cartesian3())
        // 使用Cesium库进行地理坐标转换的过程。
        // 先根据给定的法向量和距离计算出本地笛卡尔坐标(localCartesian3)，然后创建一个与给定的椭球相切的平面(tangentPlane)。
        // 接下来，使用tangentPlane对象将本地笛卡尔坐标投影到三维椭球上，得到投影后的坐标(projectCartesian3)。
        // 参照中心点计算投影点
        // multiplyByScalar（要缩放的笛卡尔坐标，要与之相乘的标量）将提供的笛卡尔分量乘以提供的标量。
        // localCartesian3.x = normal.x * plane.distance。 y,z同理
        const localCartesian3 = Cesium.Cartesian3.multiplyByScalar(normal, plane.distance, new Cesium.Cartesian3())
        // 在提供的原点与提供的椭球相切的平面。如果原点不在椭球的表面上，将使用它的表面投影。如果原点位于椭圆体的中心，则会引发异常。
        // 相切平面，tangentPlane是个平面
        const tangentPlane = new Cesium.EllipsoidTangentPlane(clipdata.center)
        // 计算提供的 2D 位置在 3D 椭球上的投影。
        const projectCartesian3 = tangentPlane.projectPointOntoEllipsoid(localCartesian3)
        // 锚点的经度纬度（弧度），高度
        const projectCart = Cesium.Cartographic.fromCartesian(projectCartesian3)
        // 锚点的经度纬度（弧度），高度
        const anchorCenter = new Cesium.Cartographic(projectCart.longitude, projectCart.latitude, cartCenter.height)
        clipdata.centers.push(Cesium.Cartographic.toCartesian(anchorCenter))
      } else if(plane.direction === 'top' || plane.direction === 'bottom') {
        const offset = Cesium.Cartesian3.multiplyByScalar(plane.normal, plane.distance, new Cesium.Cartesian3()) //将提供的笛卡尔分量乘以提供的标量。
        // 面中心点
        const anchorCenter = new Cesium.Cartographic(cartCenter.longitude, cartCenter.latitude, cartCenter.height + offset.z)

        clipdata.centers.push(Cesium.Cartographic.toCartesian(anchorCenter))
      }
    }

    // 计算单位向量
    function normalize(startPosition, endPosition) {
      const normal = new Cesium.Cartesian3()
      // subtract计算两个笛卡尔的分量差。
      Cesium.Cartesian3.subtract(startPosition, endPosition, normal)
      //normalize计算提供的笛卡尔坐标的规范化形式。
      Cesium.Cartesian3.normalize(normal, normal)
      clipdata.displayBoxInterior < 0 && Cesium.Cartesian3.negate(normal, normal)
      return normal
    }

    // 计算法向量
    clipdata.normals.push(normalize(clipdata.centers[0], clipdata.centers[1]))
    clipdata.normals.push(normalize(clipdata.centers[1], clipdata.centers[0]))
    clipdata.normals.push(normalize(clipdata.centers[2], clipdata.centers[3]))
    clipdata.normals.push(normalize(clipdata.centers[3], clipdata.centers[2]))
    clipdata.normals.push(normalize(clipdata.centers[4], clipdata.centers[5]))
    clipdata.normals.push(normalize(clipdata.centers[5], clipdata.centers[4]))

    // 更新中心点
    updateOringin()

    // viewer.entities.add({
    //   id: 'ClippingEntity1',
    //   position: new Cesium.CallbackProperty(() => {
    //     return clipdata.center
    //   }, false),
    //   orientation: quaternion,
    //   box: {
    //     dimensions: new Cesium.Cartesian3(0.5, 0.5, 0.5), //指定长宽高
    //     material: Cesium.Color.WHITE.withAlpha(1),
    //     outline: true,
    //     outlineColor: Cesium.Color.WHITE
    //   }
    // })
    // if(tileset === globalTilesetArr[0]) {
    //   const clippingEntity = viewer.entities.add({
    //     id: 'ClippingEntity' + Math.random() * 255,
    //     position: new Cesium.CallbackProperty(() => {
    //       return clipdata.center
    //     }, false),
    //     orientation: quaternion,
    //     box: {
    //       dimensions: new Cesium.CallbackProperty(updateDimensions(), false),
    //       material: Cesium.Color.WHITE.withAlpha(0),
    //       outline: true,
    //       outlineColor: Cesium.Color.WHITE
    //     }
    //   })
    //   clippingEntityArray.push(clippingEntity)
    // }
    // viewer.entities.add({
    //   position: clipdata.center,
    //   direction: direction,
    //   name: direction,
    //   // ellipsoid: {
    //   //   radii: new Cesium.Cartesian3(3, 3, 3),
    //   //   material: Cesium.Color.YELLOW
    //   // }
    //   point: {
    //     pixelSize: 10,
    //     color: Cesium.Color.RED,
    //     outlineColor: Cesium.Color.YELLOW,
    //     outlineWidth: 3.82,
    //     verticalOrigin: Cesium.VerticalOrigin.CENTER,
    //     distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE),
    //     disableDepthTestDistance: Number.MAX_VALUE
    //   }
    // })
    // 剖面框
    const clippingEntity = viewer.entities.add({
      id: 'ClippingEntity' + Math.random() * 255,
      position: new Cesium.CallbackProperty(() => {
        return clipdata.center
      }, false),
      orientation: quaternion,
      box: {
        show: true,
        dimensions: new Cesium.CallbackProperty(updateDimensions(), false),
        material: Cesium.Color.WHITE.withAlpha(0.01),
        outline: true,
        outlineWidth: 10,
        outlineColor: Cesium.Color.WHITE
      }
    })
    //
    clippingEntityArray.push(clippingEntity)
    // viewer.entities.add({
    //   position: clipdata.center,
    //   name: '111',
    //   ellipsoid: {
    //     radii: new Cesium.Cartesian3(3, 3, 3),
    //     material: Cesium.Color.YELLOW
    //   }
    // })
    console.log('clippingEntityArray', clippingEntityArray)
    // 移动真实剖面框（真实剖面框是根据transform变换的）
    const transformCenter = Cesium.Matrix4.getTranslation(tileset.root.transform, new Cesium.Cartesian3())
    console.log('transformCenter', transformCenter)
    console.log('tileset.root.transform', tileset.root.transform)
    const translation = new Cesium.Cartesian3()
    console.log('translation', translation)
    Cesium.Cartesian3.subtract(clipdata.center, transformCenter, translation)
    console.log('translation', translation)

    Cesium.Matrix3.inverse(m3, m3)
    Cesium.Matrix3.multiplyByVector(m3, translation, translation)
    const m4 = new Cesium.Matrix4()
    Cesium.Matrix4.fromTranslation(translation, m4)
    Cesium.Matrix4.multiply(clippingPlanes.modelMatrix, m4, m4)
    clippingPlanes.modelMatrix = m4
  })
}

/**
 * 名称：设置剖切对象
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
ClippingBox.quaternionToHeadingPitchRoll = function(position, quaternion) {
  const m3 = Cesium.Matrix3.fromQuaternion(quaternion) //根据提供的四元数计算 3x3 旋转矩阵。
  const m4 = Cesium.Matrix4.fromRotationTranslation(m3, position) // fromRotationTranslation第一个参数表示旋转的矩阵的左上部分，第二个参数表示平移的矩阵的右上部分。
  return Cesium.Transforms.fixedFrameToHeadingPitchRoll(m4) // 根据特定参考系中的变换计算航向-俯仰-滚动角
//  Transforms包含将位置转换为各种参考系的函数
}

/**
 * 名称：中心点计算
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
function updateOringin() {
  if(clipdata.centers.length === 6) {
    // 前后的中点
    const fbMid = Cesium.Cartesian3.midpoint(clipdata.centers[0], clipdata.centers[1], new Cesium.Cartesian3())
    // 左右的中点
    const lrMid = Cesium.Cartesian3.midpoint(clipdata.centers[2], clipdata.centers[3], new Cesium.Cartesian3())
    // 计算前后左右的中点（数据准确，只使用前后、左右或者上下均可）
    clipdata.center = Cesium.Cartesian3.midpoint(fbMid, lrMid, new Cesium.Cartesian3())
  }
}

/**
 * 名称：动态更新剖面框大小
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
function updateDimensions() {
  return () => {
    if(clipdata.centers.length === 6) {
      return new Cesium.Cartesian3(
        Cesium.Cartesian3.distance(clipdata.centers[2], clipdata.centers[3]),
        Cesium.Cartesian3.distance(clipdata.centers[0], clipdata.centers[1]),
        Cesium.Cartesian3.distance(clipdata.centers[4], clipdata.centers[5])
      )
    }
  }
}

/**
 * 名称：模拟锚点
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
function addPoint(viewer, position, direction, i, normal) {
  // let d = -(position.x * normal.x + position.y * normal.y + position.z * normal.z)
  // let d = -(position.x * normals.x + position.y * normals.y + position.z * normals.z)
  // X * normals.x + Y * normals.y + Z * normals.z + d = 0 直线方程
  // 距离 1
  // 方程一： Math.pow(X - position.x,2) + Math.pow(Y - position.y,2) +Math.pow(Z - position.z,2) = 1
  // 方程二： X * normals.x + Y * normals.y + Z * normals.z + d = 0

  // return viewer.entities.add({
  //   position: position,
  //   direction: direction,
  //   name: direction,
  //   // ellipsoid: {
  //   //   radii: new Cesium.Cartesian3(3, 3, 3),
  //   //   material: Cesium.Color.YELLOW
  //   // }
  //   point: {
  //     pixelSize: 10,
  //     color: Cesium.Color.RED,
  //     outlineColor: Cesium.Color.YELLOW,
  //     outlineWidth: 3.82,
  //     verticalOrigin: Cesium.VerticalOrigin.CENTER,
  //     distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE),
  //     disableDepthTestDistance: Number.MAX_VALUE
  //   }
  // })
  let distance = Cesium.Cartesian3.distance(clipdata.center, position)
  let multiple = clipdata.displayBoxInterior * (distance + 20) / distance //距离倍数
  let position1 = Cesium.Cartesian3.lerp(clipdata.center, position, multiple, new Cesium.Cartesian3())
  return viewer.entities.add({
    direction: direction,
    name: direction,
    index: i,
    polyline: {
      // positions: [position, position1],
      positions: new Cesium.CallbackProperty(function(i) {
        return function() {
          let x, y, z
          let t = clipdata.arrowSize[1] // 控制箭头的长度
          // 空间直线的参数方程
          // A （clipdata.center.x, clipdata.center.y, clipdata.center.z）
          // B （clipdata.centers[i].x, clipdata.centers[i].y, clipdata.centers[i].z）
          // x = t * (x1 - x2) + x2
          // y = t * (y1 - y2) + y2
          // z = t * (z1 - z2) + z2
          // 方式一 （这个方式一就是跟 ’用来求直线方程的已知两点’ 之间的距离 有关。t就是一个相对于该两点之间距离的线性插值，所以会随着两点的距离变化而变化，成正比）
          // x = t * (clipdata.center.x - clipdata.centers[i].x) + clipdata.centers[i].x
          // y = t * (clipdata.center.y - clipdata.centers[i].y) + clipdata.centers[i].y
          // z = t * (clipdata.center.z - clipdata.centers[i].z) + clipdata.centers[i].z
          // x = t * (clipdata.centers[i].x - clipdata.center.x) + clipdata.center.x
          // y = t * (clipdata.centers[i].y - clipdata.center.y) + clipdata.center.y
          // z = t * (clipdata.centers[i].z - clipdata.center.z) + clipdata.center.z

          //方式二 （这个方式相当于更新了我们的起点，在当前的起点基础上，根据方向向量（该方向向量的数值是一开始存好了的，不变）的比例去增长同等距离的△x,△y,△z，从而得到的是距离起点固定距离的一个终点。）
          let disX = clipdata.centers[i].x - clipdata.center.x
          if(disX / normal.x === Math.abs(disX / normal.x)) {
            //   同向的方向向量，不用更改方向
            x = t * normal.x + clipdata.centers[i].x
            y = t * normal.y + clipdata.centers[i].y
            z = t * normal.z + clipdata.centers[i].z
          } else {
            //   反向的方向向量，要更改方向 * （-1）
            x = t * normal.x * (-1) + clipdata.centers[i].x
            y = t * normal.y * (-1) + clipdata.centers[i].y
            z = t * normal.z * (-1) + clipdata.centers[i].z
          }
          // console.log('箭头长度', Cesium.Cartesian3.distance(clipdata.centers[i], new Cesium.Cartesian3(x, y, z), new Cesium.Cartesian3()))
          // return [clipdata.centers[i], Cesium.Cartesian3.multiplyByScalar(normal, 20, normal)]
          return [clipdata.centers[i], new Cesium.Cartesian3(x, y, z)]
          // return [
          //   clipdata.centers[i],
          //   Cesium.Cartesian3.lerp(clipdata.center, clipdata.centers[i], 1 + (20 / Cesium.Cartesian3.distance(clipdata.center, position)), new Cesium.Cartesian3())]
        }

      }(i), false),
      material: new Cesium.PolylineArrowMaterialProperty(
        clipdata.arrowColor
      ),// 折线的材质
      followSurface: true,
      width: clipdata.arrowSize[0] // 控制箭头的宽度
    }
  })
}

/**
 * 名称：创建剖面
 * 作用：通过传入的类型创建对应的剖切方式
 * 参数：target
 * 状态：
 * 网址：
 * 负责人：
 */
function createClippingPlanes() {
  // ['front', 'behind', 'left', 'right', 'top', 'bottom'];
  const clippingPlanes = new Cesium.ClippingPlaneCollection({
    planes: [
      new Cesium.ClippingPlane(new Cesium.Cartesian3(0, -1, 0), 0), // 前
      new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 1, 0), 0), // 后
      new Cesium.ClippingPlane(new Cesium.Cartesian3(1, 0, 0), 0), // 左
      new Cesium.ClippingPlane(new Cesium.Cartesian3(-1, 0, 0), 0), // 右
      new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0, -1), 0), // 上
      new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0, 1), 0) // 下

      // new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 1, 0), 0), // 前
      // new Cesium.ClippingPlane(new Cesium.Cartesian3(0, -1, 0), 0), // 后
      // new Cesium.ClippingPlane(new Cesium.Cartesian3(1, 0, 0), 0), // 左
      // new Cesium.ClippingPlane(new Cesium.Cartesian3(-1, 0, 0), 0), // 右
      // new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0, 1), 0), // 上
      // new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0, -1), 0) // 下
    ],
    unionClippingRegions: clipdata.displayBoxInterior >= 1 // true 交集
  })
  // 设定方向，以备后续拖拽使用
  const planes = clippingPlanes._planes
  for(let i = 0; i < clippingPlanes.length; ++i) {
    planes[i].direction = directions[i]
  }
  return clippingPlanes
}

